/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 *              C E D A R
 *          S O L U T I O N S       "Software done right."
 *           S O F T W A R E
 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 * Copyright (c) 2011 Kenneth J. Pronovici.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the Apache License, Version 2.0.
 * See doc/LICENSE for more information about the licensing terms.
 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 * Author   : Kenneth J. Pronovici <pronovic@ieee.org>
 * Language : Java 6
 * Project  : Secret Santa Exchange
 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package com.cedarsolutions.santa.client.internal.view;

import java.util.HashMap;
import java.util.Map;

import com.cedarsolutions.client.gwt.event.UnifiedEvent;
import com.cedarsolutions.client.gwt.event.ViewEventHandler;
import com.cedarsolutions.client.gwt.module.view.ModuleTabView;
import com.cedarsolutions.client.gwt.validation.IValidationErrorWidget;
import com.cedarsolutions.exception.InvalidDataException;
import com.cedarsolutions.santa.client.common.view.ViewUtils;
import com.cedarsolutions.santa.client.common.widget.ValidationErrorWidget;
import com.cedarsolutions.santa.shared.domain.exchange.Participant;
import com.cedarsolutions.shared.domain.LocalizableMessage;
import com.cedarsolutions.util.gwt.GwtLocalizationUtils;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Singleton;

/**
 * Exchange list tab.
 * @author Kenneth J. Pronovici <pronovic@ieee.org>
 */
@Singleton
public class EditParticipantTabView extends ModuleTabView implements IEditParticipantTabView {

    /** Reference to the UI binder. */
    private static ViewUiBinder BINDER = GWT.create(ViewUiBinder.class);

    /** UI binder interface. */
    protected interface ViewUiBinder extends UiBinder<Widget, EditParticipantTabView> {
    }

    // User interface fields fron the UI binder
    @UiField protected ValidationErrorWidget validationErrorWidget;
    @UiField protected Button saveButton;
    @UiField protected Button cancelButton;
    @UiField protected Label nameLabel;
    @UiField protected TextBox nameInput;
    @UiField protected Label nicknameLabel;
    @UiField protected TextBox nicknameInput;
    @UiField protected Label emailLabel;
    @UiField protected TextBox emailInput;
    @UiField protected Label giftGiverLabel;
    @UiField protected Label giftGiverDisplayLabel;
    @UiField protected Label giftReceiverLabel;
    @UiField protected Label giftReceiverDisplayLabel;
    @UiField(provided = true) protected DisclosurePanel assignmentDisclosure;

    // Other instance variables
    private Participant editState; // saves the current edit state for values that are not edited
    private ViewEventHandler saveHandler;
    private ViewEventHandler cancelHandler;

    /** Create the view. */
    public EditParticipantTabView() {
        this.createProvidedWidgets();  // do this before binder, otherwise we get NPE
        this.initWidget(BINDER.createAndBindUi(this));
        this.setupBinderWidgets();
    }

    /** Get the validation error widget. */
    @Override
    public IValidationErrorWidget getValidationErrorWidget() {
        return this.validationErrorWidget;
    }

    /** Translate a localizable message using this view's resources. */
    @Override
    public String translate(LocalizableMessage message) {
        InternalMessageConstants constants = GWT.create(InternalMessageConstants.class);
        return GwtLocalizationUtils.translate(message, constants, "editParticipant");
    }

    /** Get a mapping from field name to input element. */
    @Override
    public Map<String, UIObject> getValidatedFieldMap() {
        Map<String, UIObject> map = new HashMap<String, UIObject>();
        map.put("name", this.nameInput);
        map.put("nickname", this.nicknameInput);
        map.put("emailAddress", this.emailInput);
        return map;
    }

    /** Show a validation error. */
    @Override
    public void showValidationError(InvalidDataException error) {
        ViewUtils.getInstance().showValidationError(this, error);
    }

    /** Set the save handler. */
    @Override
    public void setSaveHandler(ViewEventHandler saveHandler) {
        this.saveHandler = saveHandler;
    }

    /** Get the save handler. */
    @Override
    public ViewEventHandler getSaveHandler() {
        return this.saveHandler;
    }

    /** Set the cancel handler. */
    @Override
    public void setCancelHandler(ViewEventHandler cancelHandler) {
        this.cancelHandler = cancelHandler;
    }

    /** Get the cancel handler. */
    @Override
    public ViewEventHandler getCancelHandler() {
        return this.cancelHandler;
    }

    /**
     * Set the edit state.
     * @param participant   Participant to be edited
     * @param giftGiver     Giver that is assigned to this participant
     * @param giftReceiver  Receiver that is assigned to this participant
     */
    @Override
    public void setEditState(Participant participant, Participant giftGiver, Participant giftReceiver) {
        InternalConstants constants = GWT.create(InternalConstants.class);
        String giverName = giftGiver == null ? constants.editParticipant_noAssignment() : giftGiver.getName();
        String receiverName = giftReceiver == null ? constants.editParticipant_noAssignment() : giftReceiver.getName();

        this.editState = new Participant(participant);

        this.nameInput.setText(this.editState.getName());
        this.nicknameInput.setText(this.editState.getNickname());
        this.emailInput.setText(this.editState.getEmailAddress());

        this.giftGiverDisplayLabel.setText(giverName);
        this.giftReceiverDisplayLabel.setText(receiverName);

        ViewUtils.getInstance().clearValidationErrors(this);
        this.assignmentDisclosure.setOpen(false);
    }

    /** Get the participant that is being edited, in its current state. */
    @Override
    public Participant getEditState() {
        Participant participant = new Participant(this.editState);

        participant.setName(this.nameInput.getText());
        participant.setNickname(this.nicknameInput.getText());
        participant.setEmailAddress(this.emailInput.getText());

        return participant;
    }

    /** Create and set up the provided widgets that aren't controlled by the UI binder. */
    private void createProvidedWidgets() {
        InternalConstants constants = GWT.create(InternalConstants.class);
        this.assignmentDisclosure = new DisclosurePanel(constants.editParticipant_revealAssignments());
        this.assignmentDisclosure.setOpen(false);
    }

    /** Set up the widgets that are controlled by the UI binder. */
    private void setupBinderWidgets() {
        InternalConstants constants = GWT.create(InternalConstants.class);

        this.nameLabel.setText(constants.editParticipant_nameLabel());
        this.nameLabel.setTitle(constants.editParticipant_nameTooltip());
        this.nameInput.setTitle(constants.editParticipant_nameTooltip());

        this.nicknameLabel.setText(constants.editParticipant_nicknameLabel());
        this.nicknameLabel.setTitle(constants.editParticipant_nicknameTooltip());
        this.nicknameInput.setTitle(constants.editParticipant_nicknameTooltip());

        this.emailLabel.setText(constants.editParticipant_emailAddressLabel());
        this.emailLabel.setTitle(constants.editParticipant_emailAddressTooltip());
        this.emailInput.setTitle(constants.editParticipant_emailAddressTooltip());

        this.giftGiverLabel.setText(constants.editParticipant_giftGiverLabel());
        this.giftGiverLabel.setTitle(constants.editParticipant_giftGiverTooltip());
        this.giftGiverDisplayLabel.setTitle(constants.editParticipant_giftGiverTooltip());

        this.giftReceiverLabel.setText(constants.editParticipant_giftReceiverLabel());
        this.giftReceiverLabel.setTitle(constants.editParticipant_giftReceiverTooltip());
        this.giftReceiverDisplayLabel.setTitle(constants.editParticipant_giftReceiverTooltip());

        this.saveButton.setText(constants.editParticipant_saveButton());
        this.saveButton.setTitle(constants.editParticipant_saveTooltip());
        this.saveButton.addClickHandler(new SaveClickHandler(this));

        this.cancelButton.setText(constants.editParticipant_cancelButton());
        this.cancelButton.setTitle(constants.editParticipant_cancelTooltip());
        this.cancelButton.addClickHandler(new CancelClickHandler(this));
    }

    /** Save click handler. */
    protected static class SaveClickHandler implements ClickHandler {
        protected EditParticipantTabView parent;

        public SaveClickHandler(EditParticipantTabView parent) {
            this.parent = parent;
        }

        @Override
        public void onClick(ClickEvent event) {
            if (this.parent.getSaveHandler() != null) {
                UnifiedEvent click = new UnifiedEvent(event);
                this.parent.getSaveHandler().handleEvent(click);
            }
        }
    }

    /** Cancel click handler. */
    protected static class CancelClickHandler implements ClickHandler {
        protected EditParticipantTabView parent;

        public CancelClickHandler(EditParticipantTabView parent) {
            this.parent = parent;
        }

        @Override
        public void onClick(ClickEvent event) {
            if (this.parent.getCancelHandler() != null) {
                UnifiedEvent click = new UnifiedEvent(event);
                this.parent.getCancelHandler().handleEvent(click);
            }
        }
    }

}
